package com.dmbjz.config;


import com.dmbjz.filter.LoginFilter;
import com.dmbjz.filter.UserAuthFilter;
import com.dmbjz.handler.*;
import com.dmbjz.serivice.inter.WeChatService;
import com.dmbjz.utils.TokenManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter   {


    @Autowired
    private UserDetailsService detailsService;
    @Autowired
    private PersistentTokenRepository tokenRepository;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private TokenManager tokenManager;
    @Autowired
    private WeChatService weChatService;

    /*自定义登录用户名来源和密码加密方式*/
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        auth.userDetailsService(detailsService).passwordEncoder(password());

    }

    /*自定义配置*/
    @Override
    protected void configure(HttpSecurity http) throws Exception {

       getHttp().rememberMe()
               .tokenRepository(tokenRepository)
               .tokenValiditySeconds(20)
               .userDetailsService(detailsService);  //记住我操作

       getHttp().formLogin()                                                  //进行自定义登录操作
            .loginPage("/login.html")                                         //指定登录页
            .loginProcessingUrl("/user/login")                                //登录访问路径(默认为该值)
            //.defaultSuccessUrl("/dmbjz/index")                              //认证成功后跳转路径(被successHandler覆盖后不生效)
            //.failureUrl("/login.html")                                      //认证失败后跳转路径(被failureHandler覆盖后不生效)
            .permitAll()
            .usernameParameter("loginname")                                   //表单自定义的登录名
            .passwordParameter("pwd")                                         //表单自定义的的密码名
               .successHandler(loginSendInfoHandler())                        //登录成功后的消息通知
               .failureHandler(loginFailedInfoHandler())                      //登录失败后的消息通知

            .and()
               .authorizeRequests().antMatchers("/","/user/login")                              //配置请求路径
               .permitAll()                                                                                //不需要认证即可访问
               .antMatchers("/admin/index").hasAnyAuthority("admin,superadmin")      //需要admin或superadmin权限才能访问
               .antMatchers("/admin/createAdmin").hasAnyRole("boss,shareholder")         //需要boss或shareholder角色才能访问
            .anyRequest().authenticated()                                   //其他请求需要认证
            .and().csrf().disable()                                         //关闭CSRF

            //.exceptionHandling().accessDeniedPage("/noAuth")                      //没有权限跳转的错误提示页(匿名+认证)
            .exceptionHandling().authenticationEntryPoint(new UnauthEntryPoint())   //匿名用户没有权限处理器
               .accessDeniedHandler(new LoginUnAuthHandler(tokenManager));          //认证用户没有权限处理器

            //.and()
            //.addFilter(new LoginFilter(authenticationManager(), tokenManager, redisTemplate))                       //自定义认证过滤器
            //.addFilter(new UserAuthFilter(authenticationManager(), tokenManager, redisTemplate)).httpBasic();       //自定义授权过滤器


       getHttp().logout().logoutUrl("/loginout")
               .addLogoutHandler(new TokenLogoutHandler(redisTemplate))
               .logoutSuccessUrl("/login.html").permitAll();       //注销操作

    }

    @Bean
    PasswordEncoder password(){
        return new BCryptPasswordEncoder();
    }


    /*不需要自定义认证过滤器 与 自定义授权过滤器 的登录成功后消息通知*/
    @Bean
    public AuthenticationSuccessHandler loginSendInfoHandler(){
        LoginSuccessSendMessageHandler messageHandle = new LoginSuccessSendMessageHandler();
        messageHandle.setWeChatService(weChatService);
        messageHandle.setRedisTemplate(redisTemplate);
        messageHandle.setTokenManager(tokenManager);
        return messageHandle;
    }


    /*不需要自定义认证过滤器 与 自定义授权过滤器 的登录失败后消息通知*/
    @Bean
    public AuthenticationFailureHandler loginFailedInfoHandler() {
        LoginFailedSendMessageHandler messageHandler = new LoginFailedSendMessageHandler();
        messageHandler.setDefaultFailureUrl("/login.html");       //设置登录后的跳转路径,代替failureUrl配置
        messageHandler.setWeChatService(weChatService);
        return messageHandler;
    }

}
